home *** CD-ROM | disk | FTP | other *** search
-
-
-
- The PC Assembler Tutor 114
- ______________________
-
- We can consolidate all this information into the following list:
-
- All the following addressing modes can be used with or
- without a constant:
-
- variable_name (+constant)
- [bx] (+constant)
- [si] (+constant)
- [di] (+constant)
- [bp] (+constant)
- [bx+si] (+constant)
- [bx+di] (+constant)
- [bp+si] (+constant)
- [bp+di] (+constant)
-
- This is a complete list.
-
- Thus, you can access a variable by name or with one of the eight
- pointer combinations. There are no other possibilities.
-
-
- One thing that may confuse you about an addressing statement is
- all the plusses and minuses. As an example:
-
- mov cx, -45+27[bx+22]+[-195+di]+23-44
-
- the total address is:
-
- -45+27[bx+22]+[-195+di]+23-44
-
- When the 8086 performs this instruction, it will ADD (1) BX (2)
- DI and (3) a single constant. That single constant can be a
- positive or a negative number; the 8086 will ADD all three
- elements. The '+' in front of 'di' is for convenience of the
- assembler only; [-195-di] is illegal and the assembler will
- generate an error. If you actually want the negative of what is
- in one of the registers, you must negate it before calling the
- addressing instruction:
-
- neg di
- mov cx, -45+27[bx+22]+[-195+di]+23-44
-
- once again, the only allowable forms are +[di], [di] or [+di].
- Either -[di] or [-di] will generate an assembler error.
-
-
- If you ever see a technical description of the addressing modes,
- you will find a list of 24 different machine codes. The reason
- for this is that:
-
- [bx]
- [bx] + byte constant
- [bx] + word constant
-
- are three different machine codes. Here is a listing of the same
- machine instruction with the three different styles:
-
-
-
-
-
- Chapter 11 - Addressing Modes 115
- _____________________________
-
-
- MACHINE CODE ASSEMBLER INSTRUCTION
-
- 03 04 add ax, [si]
- 03 44 1B add ax, [si+27]
- 03 44 E5 add ax, [si-27]
- 03 84 5BA7 add ax, [si+23463]
- 03 84 A459 add ax, [si-23463]
-
-
- (27d = 1Bh , 23463d = 5BA7h). The first byte of code (03) is the
- add (word) instruction. The second byte is the addressing code,
- and the third and fourth bytes (if any) are the constant (in
- hex). Addressing code 04 is: (ax, [si]). Addressing code 44 is:
- (ax, [si] + byte constant). Addressing code 84 is: (ax, [si] +
- word constant). The fact that there are three different machine
- codes is of concern to the assembler, not to you. It is the
- assembler's job to make the machine code as efficient as
- possible. It is your job to write quality, robust code.
-
-
- SEGMENT OVERRIDES
-
- So far, we haven't talked about segment registers. You will
- remember from the last chapter that the 8086 assumes that a named
- variable is in the DS segment:
-
- mov ax, variable1
-
- If it isn't, the Microsoft assembler puts the correct segment
- override in the machine code. The segment overrides are:
-
- SEGMENT OVERRIDE MACHINE CODE (hex)
- CS 2E
- DS 3E
- ES 26
- SS 36
-
- As an example:
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
-
- 2E: 03 06 0000 R add ax, variable3
- 26: 2B 1E 0000 R sub bx, variable2
- 31 36 0000 R xor variable1, si ; no override
- 36: 21 3E 00C8 R and variable4, di
-
- when the different variables were in segments with different
- ASSUME statements. If you don't remember this, you should reread
- the section on overrides in the last chapter. Remember, the colon
- is in the listing only to tell you that we have a segment
- override. The colon is not in the machine code.
-
-
-
-
-
-
-
-
-
- The PC Assembler Tutor 116
- ______________________
-
- What about pointers? The natural segment for anything with [bp]
- is SS, the stack segment.{1} Everything else has DS as its
- natural segment. The natural segments are:
-
- (1) DS
-
- variable + (constant)
- [bx] + (constant)
- [si] + (constant)
- [di] + (constant)
- [bx+si] + (constant)
- [bx+di] + (constant)
-
-
- (2) SS
-
- [bp] + (constant)
- [bp+si] + (constant)
- [bp+di] + (constant)
-
- where the constant is always optional. Can you use segment
- overrides? Yes, in all cases.{2} Here is some assembler code
- along with the machine code which was generated.
-
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
-
- 26: 03 07 add ax, es:[bx]
- 2E: 01 05 add cs:[di], ax
- 36: 2B 44 11 sub ax, ss:[si+17]
- 2E: 29 46 00 sub cs:[bp], ax
- 3E: 33 03 xor ax, ds:[bp+di]
- 26: 31 02 xor es:[bp+si], ax
- 26: 89 43 16 mov es:[bp+di+22], ax
-
-
- 03 04 add ax, [si]
- 03 44 1B add ax, [si+27]
- 03 84 A459 add ax, [si-23463]
- 26: 03 04 add ax, es:[si]
- 26: 03 44 1B add ax, es:[si+27]
- 26: 03 84 A459 add ax, es:[si-23463]
-
-
- (17d = 11h, 22d = 16h, 27d = 1Bh, -23463d = 0A459h). The first
- number (which is followed by a colon) is the segment override
- that the assembler has inserted in the machine code. Remember,
- the colon is in the listing to inform you that an override is
- ____________________
-
- 1 We will see why when we look at subroutines. BP is called
- the base pointer [bp] and is used in a special way.
-
- 2 There are some special instructions for two independent
- pointers which we will cover at the end of the book. These allow
- segment overrides but force the override to refer to the first
- pointer.
-
-
-
-
- Chapter 11 - Addressing Modes 117
- _____________________________
-
- involved; it is not in the machine code itself.
-
- Unfortunately, when you use pointers you must put the override
- into the assembler instructions yourself. The assembler has no
- way of knowing that you want an override. This can cause some
- truly gigantic errors (if you reference a pointer seven times and
- forget the override once, the 8086 will access the wrong segment
- that one time), and those errors are extremely difficult to
- detect.
-
- As you can see from above, you put the override in the
- instructions by writing the appropriate segment (CS, DS, ES or
- SS) followed by a colon. As always, it is your responsibility to
- make sure that the segment register holds the address of the
- appropriate segment before using an override.
-
-
- We have talked about two different types of constants in the
- chapter, a constant which is part of the address:
-
- mov ax, [bx+17]
- add [si+2190], dx
- and [di-8179], cx
-
- and a constant which is a number to used for an arithmetical or
- logical operation:
-
- add ax, 17
- sub dl, 45
- add dx, 22187
-
- They are both part of the machine instruction, and are
- unchangeable (true constants). This machine code is going to be
- difficult to read, so just look for (1) the constant DATA and (2)
- the constant in the ADDRESS. All constants in the assembler
- instructions are in hex so that they look the same as in the
- listing of the machine code. Here's a listing of different
- combinations.
-
-
- 1. Pointer + constant as an address:
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
- 01 44 1B add [si+1Bh], ax
- 29 85 0A04 sub [di+0A04h], ax
- 30 5C 1F xor [si+1Fh], bl
- 20 9E 1FAB and [bp+1FABh], bl
-
- 2. Arithmetic instruction with a constant:
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
- 05 1065 add ax, 1065h
- 2D 6771 sub ax, 6771h
- 80 F3 37 xor bl, 37h
- 80 E3 82 and bl, 82h
-
- 3. Pointer + constant as an address; arithmetic with a constant
-
-
-
-
- The PC Assembler Tutor 118
- ______________________
-
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
- 81 44 1B 1065 add [si+1Bh], 1065h
- 81 AD 0A04 6771 sub [di+0A04h], 6771h
- 80 74 1F 37 xor [si+1Fh], BYTE PTR 37h
- 80 A6 1FAB 82 and [bp+1FABh], BYTE PTR 82h
-
-
- You will notice that the ADD instruction (as well as the other
- instructions) changes machine code depending on the complete
- format of the instruction (byte or word? to a register or from a
- register? what addressing mode? is AX one of the registers?).
- That's part of the 8086 machine language encoding, and it makes
- the 8086 machine code extremely difficult to decipher without a
- table listing all the options.
-
-
- OFFSET AND SEG
-
- There are two special instructions that the assembler has -
- offset and seg. For any variable or label, offset gives the
- offset from the beginning of the segment, and seg gives the
- segment address. If you write:
-
- mov ax, offset variable1
-
- the assembler will calculate the offset of variable1 and put it
- in the machine code. It also signals the linker and loader; if
- the linker should change the offset during linking, it will also
- adjust this number. If you write:
-
- mov dx, seg variable1
-
- The assembler will signal to the linker and the loader that you
- want the address of the segment that variable1 is in. The linker
- and loader will put it in the machine code at that spot. You
- don't need to know the name of the segment. The linker takes care
- of that. We will use the seg operator later.
-
-
- LEA
-
- LEA (load effective address) is a completely different animal. It
- allows you to use any addressing mode to put an address in a
- register. One of the addressing modes covered before was for the
- following code:
-
- xor dx, 45+[di+23][bx+15]-94
-
- The 8086 added DI, BX and the constant to calculate the address.
- It then XOR'ed the variable at that address with DX. If you
- write:
-
- lea dx, 45+[di+23][bx+15]-94
-
- the 8086 will add DI, BX and the constant to calculate the
- address. It will then put the ADDRESS in DX. LEA can use any
-
-
-
-
- Chapter 11 - Addressing Modes 119
- _____________________________
-
- addressing mode to calculate an address. The machine code looks
- almost the same:
-
- MACHINE CODE ASSEMBLER INSTRUCTIONS
-
- 33 51 F5 xor dx, 45+[di+23][bx+15]-94
- 8D 51 F5 lea dx, 45+[di+23][bx+15]-94
-
- The first byte of the machine code is the instruction and the
- second and third byte are the addressing mode.
-
- You almost never need LEA. It is slower than:
-
- mov dx, offset variable1
-
- However, when the addressing gets complicated (perhaps 1% of the
- time), it's nice to have. Remember, it will calculate ANY 8086
- addressing mode.
-
- Let's run a program so we can see what actually happens with LEA
-
- ;lea.asm
- ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE
- variable1 dw ?
- ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE
-
- ; + + + + START CODE BELOW THIS LINE
- ; reg style
- mov si_byte, 1 ; signed
- lea ax, ax_byte
- call set_reg_style
-
- mov bp, 0 ; clear unused registers
- mov di, 0
-
- ;lea and mov show the two ways to address variable1
- lea ax, variable1 ; effective address
- mov bx, offset variable1 ; offset
- call show_regs_and_wait
-
- lea_loop:
- mov si, 0 ; clear registers
- mov dx, 0
- mov cx, 0
- mov bx, 0
- mov ax, 0
- call show_regs
-
- call get_unsigned ; unsigned for bx
- mov bx, ax
- mov ax, 0 ; blank ax
- call show_regs
-
- call get_signed ; signed for si
- mov si, ax
-
- mov ax, 0 ; blank ax
-
-
-
-
- The PC Assembler Tutor 120
- ______________________
-
- lea cx, [bx+si]+100 ; addresses to cx and dx
- lea dx, [si+bx-100]
- call show_regs_and_wait
-
- jmp lea_loop
- ; + + + + END CODE ABOVE THIS LINE
-
- The first part of the program shows that LEA and MOV give the
- same offset address. Then we enter the loop. It gets an unsigned
- number, puts it in BX, gets a signed number, puts it in SI, then
- uses LEA to calculate [bx+si+100] and [bx+si-100]. The plus and
- minus 100 is simply to show you a difference of 200 in the two
- results. BX and SI could also have contained (1) both signed
- numbers or (2) both unsigned numbers. It doesn't make any
- difference. This program has a signed and an unsigned number for
- variety. Of special interest to you shold be when [bx+si] is
- within 100 of 65536 (or 0). One of the results will be > 0 while
- the other result will be < 65536 The address value wraps around
- from 65535 -> 0. Note that with minor alteration, this program
- can be used to look at ANY addressing mode that uses pointers.
-
- You should make two executable files for this. First:
-
- link lea+asmhelp
-
- and the second:
-
- link asmhelp+lea
-
- Give them different names and run them. Note the offset values
- for:
-
- lea ax, variable1
- mov bx, offset variable1
-
- With lea+asmhelp you should have an offset of 8 for variable1
- since there are 8 bytes in the array (ax_byte, bx_byte, etc.).
- This array appears before variable1 in the data segment. When you
- link it the other way (asmhelp+lea), all the data for asmhelp.obj
- is in front of your data and the offset should be something
- completely different for variable1.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Chapter 11 - Addressing Modes 121
- _____________________________
-
- SUMMARY
-
- These are the natural (default) segments of all addressing modes:
-
- (1) DS
-
- variable + (constant)
- [bx] + (constant)
- [si] + (constant)
- [di] + (constant)
- [bx+si] + (constant)
- [bx+di] + (constant)
-
-
- (2) SS
-
- [bp] + (constant)
- [bp+si] + (constant)
- [bp+di] + (constant)
-
- Where the constant is optional. Segment overrides may be used.
- The segment overrides are:
-
- SEGMENT OVERRIDE MACHINE CODE (hex)
- CS: 2E
- DS: 3E
- ES: 26
- SS: 36
-
-
- OFFSET
-
- The reserved word 'offset' tells the assembler to calculate the
- offset of the variable from the beginning of the segment.
-
- mov ax, offset variable2
-
-
- SEG
-
- The reserved word 'seg' tells the assembler, linker and loader to
- get the segment address of the segment that the variable is in.
-
- mov ax, seg variable2
-
- LEA
-
- LEA calculates an address using any of the 8086 addressing modes,
- then puts the address in a register.
-
- lea cx, [bp+di+27]
-
-